package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"time"
)

type Riff1 struct {
	id   []byte
	size []byte
	typ  []byte
}
type Format1 struct {
	id            []byte
	size          []byte //16正常格式，18（12h）带有附加信息头
	audioFormat   []byte //格式种类（值为1时，表示数据为线性PCM编码）
	numChannels   []byte
	sampleRate    []byte
	byteRate      []byte
	blockAlign    []byte
	bitsPerSample []byte
}
type WavData1 struct {
	id   []byte //1414744396时为fact
	size []byte
	data []byte
}
type WavFile1 struct {
	riff    Riff1
	format  Format1
	wavData WavData1
	fact    FactDat
	fsig    bool
}
type FactDat struct {
	id   []byte
	size []byte
	data []byte
}

func main() {
	path := "tts1.wav"
	var wav1 WavFile1
	var err error
	wav1, err = WavFilePag(path)
	path = "tts2.wav"
	var wav2 WavFile1
	wav2, err = WavFilePag(path)
	//path = "tts3.wav"
	//var wav3 WavFile1
	//wav3, err = WavFilePag(path)
	if err != nil {
		fmt.Println("ioutil WriteFile error: ", err)
	}
	//fmt.Println(BinaryStringToInt1(ListToBinaryString1(wav1.format.size)))
	//fmt.Println(BinaryStringToInt1(ListToBinaryString1(wav1.format.audioFormat))) //声道数
	//fmt.Println(BinaryStringToInt1(ListToBinaryString1(wav1.format.numChannels))) //声道数
	fmt.Println(BinaryStringToInt1(ListToBinaryString1(wav1.format.sampleRate)))    //采样率
	fmt.Println(BinaryStringToInt1(ListToBinaryString1(wav1.format.bitsPerSample))) //采样位数
	//fmt.Println(wav1.wavData.id)
	len1 := BinaryStringToInt1(ListToBinaryString1(wav1.wavData.size))
	//len2:=BinaryStringToInt1(ListToBinaryString1(wav2.wavData.size))
	//len3:=BinaryStringToInt1(ListToBinaryString1(wav3.wavData.size))
	outlen := BinaryStringToInt1(ListToBinaryString1(wav1.riff.size))
	var newWav WavFile1
	newWav = deepCopy1(wav1)
	sampleRate := BinaryStringToInt1(ListToBinaryString1(wav1.format.sampleRate))
	bitsPerSample := BinaryStringToInt1(ListToBinaryString1(wav1.format.bitsPerSample))
	newWav.wavData.data = append(newWav.wavData.data, addSilentSegment(5000, sampleRate, bitsPerSample)...)
	newWav.wavData.data = append(newWav.wavData.data, wav2.wavData.data...)
	//newWav.wavData.data = append(newWav.wavData.data, wav3.wavData.data...)
	newWav.wavData.size = intToByte1(len(newWav.wavData.data))
	newWav.riff.size = intToByte1(len(newWav.wavData.data) + outlen - len1)
	path = "ttsall-" + time.Now().Format("20190513-0000") + ".wav"
	err = WavFileWrite(newWav, path)
	if err != nil {
		fmt.Println("ioutil WriteFile error: ", err)
	}
}

//文件输出
func WavFileWrite(new WavFile1, path string) (err error) {
	con1 := ObjToByte1(new)
	err = ioutil.WriteFile(path, con1, 0666)
	if err != nil {
		fmt.Println("ioutil WriteFile error: ", err)
	}
	return
}

//从文件打包
func WavFilePag(path string) (old WavFile1, err error) {
	f, err := os.Open(path)
	if err != nil {
		fmt.Println("os Open error: ", err)
	}
	defer f.Close()
	//读取文件全部内容
	b, err := ioutil.ReadAll(f)
	if err != nil {
		fmt.Println("ioutil ReadAll error: ", err)
	}
	old = WavPag(b)
	return
}

//打包
func WavPag(b []byte) WavFile1 {
	var sig bool = false
	var riffOld Riff1
	riffOld.id = b[:4]
	riffOld.size = b[4:8]
	riffOld.typ = b[8:12]
	var formatOld Format1
	formatOld.id = b[12:16]
	formatOld.size = b[16:20]
	formatOld.audioFormat = b[20:22]
	formatOld.numChannels = b[22:24]
	formatOld.sampleRate = b[24:28]
	formatOld.byteRate = b[28:32]
	formatOld.blockAlign = b[32:34]
	formatOld.bitsPerSample = b[34:36]
	var wavDatOld WavData1
	var fact FactDat
	if BinaryStringToInt1(ListToBinaryString1(b[36:40])) == 1414744396 {
		fact.id = b[36:40]
		fact.size = b[40:44]
		fact.data = b[44:48]
		wavDatOld.id = b[48:52]
		wavDatOld.size = b[56:60]
		wavDatOld.data = b[60:]
		sig = true
	} else {
		wavDatOld.id = b[36:40]
		wavDatOld.size = b[40:44]
		wavDatOld.data = b[44:]

	}
	var old WavFile1
	old.format = formatOld
	old.riff = riffOld
	old.wavData = wavDatOld
	if sig {
		old.fact = fact
		old.fsig = true
	}
	return old
}

//int转byte[]4*8=32
func ObjToByte1(val WavFile1) (res []byte) {
	res = append(res, val.riff.id...)
	res = append(res, val.riff.size...)
	res = append(res, val.riff.typ...)

	res = append(res, val.format.id...)
	res = append(res, val.format.size...)
	res = append(res, val.format.audioFormat...)
	res = append(res, val.format.numChannels...)
	res = append(res, val.format.sampleRate...)
	res = append(res, val.format.byteRate...)
	res = append(res, val.format.blockAlign...)
	res = append(res, val.format.bitsPerSample...)
	if val.fsig {
		res = append(res, val.fact.id...)
		res = append(res, val.fact.size...)
		res = append(res, val.fact.data...)
	}
	res = append(res, val.wavData.id...)
	res = append(res, val.wavData.size...)
	res = append(res, val.wavData.data...)

	return
}

//int转byte[]4*8=32
func intToByte1(val int) (res []byte) {
	str := ToBinaryString1(val)
	for i := len(str); i < 32; i++ {
		str = "0" + str
	}
	var tempInt [4]int
	tempInt[0] = BinaryStringToInt1(str[24:32])
	tempInt[1] = BinaryStringToInt1(str[16:24])
	tempInt[2] = BinaryStringToInt1(str[8:16])
	tempInt[3] = BinaryStringToInt1(str[:8])

	res = make([]byte, 4)
	for index := 0; index < 4; index++ {
		res[index] = byte(tempInt[index])
	}
	return
}

//byte[]转字符串
func ListToBinaryString1(b []byte) (str string) {
	str = ""
	for i := 0; i < len(b); i++ {
		str = ToBinaryString1(int(b[i])) + str
	}
	return
}

//int转字节字符串
func ToBinaryString1(val int) (str string) {
	str = ""
	for val/2 > 0 {
		res := val % 2
		str = "" + strconv.Itoa(res) + str
		val = val / 2
	}
	str = "" + strconv.Itoa(val) + str
	for i := len(str); i < 8; i++ {
		str = "0" + str
	}
	return
}

//string转int
func BinaryStringToInt1(str string) (res int) {
	res = 0
	sum := 1
	for i := len(str); i > 0; i-- {
		num, _ := strconv.Atoi(str[i-1 : i])
		res = res + sum*num
		sum = sum * 2
	}
	return
}

//深拷贝
func deepCopy1(src WavFile1) WavFile1 {

	var wavDatOld WavData1
	wavDatOld.id = src.wavData.id
	wavDatOld.size = src.wavData.size
	wavDatOld.data = src.wavData.data

	var formatOld Format1
	formatOld.id = src.format.id
	formatOld.size = src.format.size
	formatOld.audioFormat = src.format.audioFormat
	formatOld.numChannels = src.format.numChannels
	formatOld.sampleRate = src.format.sampleRate
	formatOld.byteRate = src.format.byteRate
	formatOld.blockAlign = src.format.blockAlign
	formatOld.bitsPerSample = src.format.bitsPerSample

	var riffOld Riff1
	riffOld.id = src.riff.id
	riffOld.size = src.riff.size
	riffOld.typ = src.riff.typ

	var dst WavFile1
	dst.format = formatOld
	dst.riff = riffOld
	dst.wavData = wavDatOld

	return dst
}

//增加静音段ms为单位
func addSilentSegment(len, sampleRate, bitsPerSample int) (data []byte) {
	var second int = 1000
	num := len * sampleRate / second
	num = num * (bitsPerSample / 8) //乘以每个点字节数
	for i := 0; i < num; i++ {
		b := byte(0)
		data = append(data, b)
	}
	return
}
